<?php
// +----------------------------------------------------------------------
// | ZGUAN [ 致力于帮助更多的中小企业物联网转型 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.zguan.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ZGUAN 并不是自由软件，未经许可不能去掉ZGUAN 相关版权
// +----------------------------------------------------------------------
// | Author: ZGUAN Team <admin@zguan.cn>  0769-82282996  15899929162
// +----------------------------------------------------------------------
namespace app\controller\api\energy;

use think\App;
use app\controller\api\Base;
use app\validate\energy\EnergyMeterValidate;
use app\validate\energy\EnergyMeterDayValidate;
use app\common\repositories\items\ItemsBasicRepository;
use app\common\repositories\energy\EnergyMeterRepository;
use app\common\repositories\energy\EnergyQrcodeRepository;
use app\common\repositories\energy\EnergyMeterLogRepository;
use app\common\repositories\energy\EnergyMeterDayRepository;
use app\common\repositories\energy\EnergyOperateLogRepository;
use app\common\repositories\energy\EnergyBalanceLogRepository;

class EnergyMeter extends Base
{
    protected $repository;

    public function __construct(App $app, EnergyMeterRepository $repository)
    {
        parent::__construct($app);

        $this->repository = $repository;
    }

    public function list()
    {
        $where = $this->request->param([
            'property_id' => '',
            'room_id' => '',
            'plan_id' => '',
            'plan_type' => '',
            'is_public' => '',
            'status' => '',
            'keywords' => ''
        ]);
        [$page, $limit] = $this->getPage();
        $where['add_uid'] = $this->request->userId();
        $res = $this->repository->getApiList($where, $page, $limit, $this->request->propertyId);
        return app('api_return')->success($res);
    }

    /**
     * 根据二维码获取设备信息
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-06-04 14:34
     */
    public function getCodeMeter()
    {
        $param = $this->request->param([
            'energy_code' => '',
        ]);
        if (!$param['energy_code']) {
            return $this->error('非法操作');
        }
        /** @var EnergyQrcodeRepository $energyQrcodeRepository */
        $energyQrcodeRepository = app()->make(EnergyQrcodeRepository::class);
        $codeInfo = $energyQrcodeRepository->getSearch([])
            ->where('items_id', $this->request->propertyId)
            ->where('energy_code', $param['energy_code'])
            ->field('energy_type,energy_code,energy_no,energy_id,is_bind')
            ->find();
        if (!$codeInfo) {
            return $this->error('非法操作');
        }
        if ($codeInfo['energy_type'] <= 0 && $codeInfo['energy_id'] <= 0) {
            return $this->error('未生产');
        }
        if ($codeInfo['is_bind'] != 1) {
            return $this->error('未绑定');
        }
        return app('api_return')->success($codeInfo);
    }

    /**
     * 批量添加设备
     * @return mixed
     *
     * @author Amos
     * 2024-05-18 13:51
     */
    public function addBatch()
    {
        $param = $this->request->param([
            'property_id' => '',
            'plan_type' => '',
            'wit_type' => '',
            'meter_data' => '',
        ]);
        validate(EnergyMeterValidate::class)->scene('batchAdd')->check($param);
        $res = $this->repository->batchAdd($param, $this->request->propertyId, $this->request->userId());
        return app('api_return')->success($res);
    }


    /**
     * 扫码添加设备
     * @return mixed
     *
     * @author Amos
     * 2024-05-18 16:17
     */
    public function codeAdd()
    {
        $param = $this->request->param([
            'property_id' => '',
            'plan_type' => '',
            'energy_code' => '',
            'energy_name' => '',
            'unit_price' => '',
            'pay_service_fee' => '',
            'beilv' => '',
        ]);
        validate(EnergyMeterValidate::class)->scene('codeAdd')->check($param);
        $res = $this->repository->codeAdd($param, $this->request->propertyId, $this->request->userId());
        return app('api_return')->success($res);
    }

    /**
     * 编辑设备信息
     * @param $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 16:33
     */
    public function edit(int $id)
    {
        $info = $this->repository->get($id);
        if (!$info) {
            return app('api_return')->error('非法操作');
        }
        $param = $this->request->param([
            'wit_type' => '',
            'energy_type' => '',
            'energy_no' => '',
            'energy_name' => '',
        ]);
        if ($this->repository->fieldExists('energy_no', $param['energy_no'], $id)) {
            return $this->error($param['energy_no'] . '已存在');
        }
        $res = $this->repository->editInfo($info, $param, $this->request->userId());
        return app('api_return')->success($res);
    }


    /**
     *  删除设备
     * @param $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 16:47
     */
    public function delete(int $id)
    {
        $info = $this->repository->get($id);
        if (!$info) {
            return app('api_return')->error('数据不存在');
        }
        if ($info['add_uid'] != $this->request->userId()) {
            return app('api_return')->error('非法操作，非创建人禁止删除');
        }
        $res = $this->repository->batchDelete([$id], $this->request->userId());
        if ($res) {
            return $this->successText('删除成功');
        } else {
            return $this->error('删除失败');
        }
    }

    /**
     *  查询设备详情
     * @param $id
     * @return mixed
     * @throws \think\db\exception\DbException
     *
     * @author Amos
     * 2024-05-18 17:44
     */
    public function detail(int $id)
    {
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }
        $info = $this->repository->getDetail($id);
        if (!$info) {
            return app('api_return')->error('数据不存在');
        }
        return app('api_return')->success($info);
    }


    /**
     * 人工抄读
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 17:19
     */
    public function meterReading(int $id)
    {
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }
        $param = $this->request->param([
            'read_z' => '',
            'read_j' => '',
            'read_f' => '',
            'read_p' => '',
            'read_g' => '',
            'day_time' => '',
        ]);
        $param['day_time'] = $param['day_time'] ?: date('Y-m-d');
        validate(EnergyMeterDayValidate::class)->scene('add')->check($param);
        $meterInfo = $this->repository->getDetail($id);
        if ($meterInfo['unit_price'] <= 0 && $meterInfo['plan_id'] <= 0) {
            return $this->error('请先设置收费方案');
        }
        if ($meterInfo['read_time'] > date('Y-m-d')) {
            return $this->error('每日限抄读一次');
        }

        if ($meterInfo['mode_type'] == 2) {
            if ($param['read_j'] <= $meterInfo['read_j']) {
                return $this->error('尖时 用量读数必须大于上期读数');
            }
            if ($param['read_f'] <= $meterInfo['read_f']) {
                return $this->error('谷时 用量读数必须大于上期读数');
            }
            if ($param['read_p'] <= $meterInfo['read_p']) {
                return $this->error('平时 用量读数必须大于上期读数');
            }
            if ($param['read_g'] <= $meterInfo['read_g']) {
                return $this->error('谷时 用量读数必须大于上期读数');
            }
            $param['read_z'] = bcadd($param['read_j'], $param['read_f'], 2);
            $param['read_z'] = bcadd($param['read_z'], $param['read_p'], 2);
            $param['read_z'] = bcadd($param['read_z'], $param['read_g'], 2);
        } else {
            if ($param['read_z'] <= $meterInfo['read_z']) {
                return $this->error('本期 用量读数必须大于上期读数');
            }
        }
        $this->repository->manuallyMeterReading($meterInfo, $param, $this->request->userId());
        return app('api_return')->success([], '抄读成功');
    }


    /**
     * 实时抄读设备
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 18:15
     */
    public function autoReadCopy(int $id)
    {
        $param = $this->request->param([
            'remark' => '',
        ]);
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }
        $meterInfo = $this->repository->get($id);
        if (!$meterInfo) {
            return $this->error('数据不存在');
        }
        if ($meterInfo['wit_type'] != 1) {
            return $this->error('该表不支持此操作');
        }

        ##  优先查询缓存数据
        /** @var EnergyMeterDayRepository $energyMeterDayRepository */
        $energyMeterDayRepository = app()->make(EnergyMeterDayRepository::class);
        if (($res = $energyMeterDayRepository->getDayCacheData($meterInfo['id']))) {
            return $this->success([
                'status' => 1,
                'data' => $res
            ]);
        }

        ## 优先获取电表正在执行中的操作记录
        /** @var EnergyOperateLogRepository $operateLogRepository */
        $operateLogRepository = app()->make(EnergyOperateLogRepository::class);
        if (($res = $operateLogRepository->getRuningLogInfo($meterInfo['id'], 'call_reading'))) {
            return $this->success([
                'request_id' => $res['request_id']
            ]);
        }
        $param['type'] = 'call_reading';
        $res = $this->repository->autoReadCopy($meterInfo, $param, $this->request->userId());
        return $this->success([
            'status' => 1,
            'request_id' => $res['request_id']
        ], '提交成功');
    }

    /**
     * 切换收费类型
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 20:06
     */
    public function switchPlanType(int $id)
    {
        $param = $this->request->param([
            'plan_type' => '',
            'balance' => 0
        ]);
        validate(EnergyMeterValidate::class)->scene('switchPlanType')->check($param);
        $meterInfo = $this->repository->get($id);
        if (!$meterInfo) {
            return $this->error('数据不存在');
        }
        if ($param['plan_type'] == $meterInfo['plan_type']) {
            $remark = '';
            switch ($meterInfo['plan_type']) {
                case '1':
                    $remark = '后付费';
                    break;
                case '2':
                    $remark = '预付费';
                    break;
            }
            return $this->error('当前收费类型就是' . $remark . ',无需切换');
        }
        $this->repository->switchPlanType($meterInfo, $param, $this->request->userId());
        return $this->successText('切换成功');
    }


    /**
     * 设备合闸
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 21:37
     */
    public function onEnergyMeter(int $id)
    {
        $param = $this->request->param([
            'remark' => ''
        ]);
        if ($param['remark'] == '') {
            return $this->error('请输入备注说明');
        }
        if (!$this->repository->exists($id)) {
            return $this->error('数据不存在');
        }
        $meterInfo = $this->repository->get($id);
        if (!$meterInfo) {
            return $this->error('设备不存在');
        }
        if ($meterInfo['wit_type'] != 1) {
            return $this->error('非智能设备不支持此操作');
        }
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }
        $param['type'] = 'on';
        $res = $this->repository->onEnergyMeter($meterInfo, $param, $this->request->userId());
        return $this->success([
            'request_id' => $res['request_id']
        ]);
    }

    /**
     * 设备拉闸
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 21:37
     */
    public function offEnergyMeter(int $id)
    {
        $param = $this->request->param([
            'remark' => ''
        ]);
        if ($param['remark'] == '') {
            return $this->error('请输入备注说明');
        }
        if (!$this->repository->exists($id)) {
            return $this->error('数据不存在');
        }
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }
        $meterInfo = $this->repository->get($id);
        if (!$meterInfo) {
            return $this->error('设备不存在');
        }
        if ($meterInfo['wit_type'] != 1) {
            return $this->error('非智能设备不支持此操作');
        }
        $param['type'] = 'off';
        $res = $this->repository->offEnergyMeter($meterInfo, $param, $this->request->userId());
        return $this->success([
            'request_id' => $res['request_id']
        ]);
    }

    /**
     * 状态更新
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 21:43
     */
    public function updateOnOff(int $id)
    {
        $param = $this->request->param([
            'remark' => ''
        ]);
        if ($param['remark'] == '') {
            return $this->error('请输入备注说明');
        }
        if ($id <= 0) {
            return $this->error('参数错误');
        }
        if (!$this->repository->exists($id)) {
            return $this->error('数据不存在');
        }
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }
        $meterInfo = $this->repository->get($id);
        if (!$meterInfo) {
            return $this->error('设备不存在');
        }
        if ($meterInfo['wit_type'] != 1) {
            return $this->error('非智能设备不支持此操作');
        }
        $param['type'] = 'call_status';
        $res = $this->repository->updateOnOff($meterInfo, $param, $this->request->userId());
        return $this->success([
            'request_id' => $res['request_id']
        ]);
    }


    /**
     *  智能表结果回调
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 13:37
     */
    public function queryOperateResult()
    {
        $requestId = $this->request->param('request_id');
        if (!$requestId) {
            return app('api_return')->error('参数错误');
        }
        /** @var EnergyOperateLogRepository $energyOperateLogRepository */
        $energyOperateLogRepository = app()->make(EnergyOperateLogRepository::class);
        $res = $energyOperateLogRepository->getSearch([])
            ->where('request_id', $requestId)
            ->find();
        if ($res) {
            return $this->success([
                'status' => $res['status'],
                'msg' => ($res['status'] === 0 ? '执行中' : ($res['status'] === 1 ? '成功' : ($res['status'] === 2 ? $res['fail_desc'] : ''))),
                'data' => $res['result_content']['data']['response']['messageData'] ?? null
            ]);
        }
        return $this->success(null);
    }

    /**
     * 日用量列表
     * @param EnergyMeterDayRepository $dayRepository
     * @return mixed
     *
     * @author Amos
     * 2024-05-18 21:51
     */
    public function dayMeterList(EnergyMeterDayRepository $repository)
    {
        $where = $this->request->param([
            'property_id' => '',
            'energy_id' => '',
            'room_id' => '',
            'time' => '',
        ]);
        [$page, $limit] = $this->getPage();
        $res = $repository->getItemsList($where, $page, $limit, $this->request->propertyId);
        return $this->success($res);
    }

    /**
     * 设备日志记录
     * @param EnergyMeterLogRepository $logRepository
     * @return mixed
     *
     * @author Amos
     * 2024-05-18 22:05
     */
    public function getMeterLog(EnergyMeterLogRepository $repository)
    {
        $where = $this->request->param([
            'energy_id' => '',
            'keywords' => '',
        ]);
        [$page, $limit] = $this->getPage();
        $res = $repository->getItemsList($where, $page, $limit, $this->request->propertyId);
        return $this->success($res);
    }

    /**
     * 设备操作记录
     * @param EnergyMeterLogRepository $logRepository
     * @return mixed
     *
     * @author Amos
     * 2024-05-18 22:05
     */
    public function getOperateLog(EnergyOperateLogRepository $repository)
    {
        $where = $this->request->param([
            'energy_id' => '',
            'keywords' => '',
        ]);
        [$page, $limit] = $this->getPage();
        $res = $repository->getItemsList($where, $page, $limit, $this->request->propertyId);
        return $this->success($res);
    }


    /**
     * 余额变动日志
     * @param EnergyBalanceLogRepository $repository
     * @return mixed
     *
     * @author Amos
     * 2024-05-18 22:19
     */
    public function getBalanceLog(EnergyBalanceLogRepository $repository)
    {
        $where = $this->request->param([
            'energy_id' => '',
            'keywords' => '',
        ]);
        [$page, $limit] = $this->getPage();
        $res = $repository->getItemsList($where, $page, $limit, $this->request->propertyId);
        return $this->success($res);
    }

    /**
     *  设备充值
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 22:26
     */
    public function rechargePay(int $id)
    {
        if (!$this->repository->exists($id)) {
            return $this->error('数据不存在');
        }
        $param = $this->request->param([
            'pay_method' => '',
            'is_type' => '',
            'pay_type' => '',
            'pay_amount' => '',
            'remark' => '',
        ]);
        validate(EnergyMeterValidate::class)->scene('recharge')->check($param);
        $meterInfo = $this->repository->get($id);
        if (!$meterInfo) {
            return $this->error('数据不存在');
        }
        if ($meterInfo['plan_type'] == 1) {
            return $this->error('后付费不支持充值');
        }
        $this->repository->rechargeInfo($meterInfo['id'], $param, $this->request->userId());
        return $this->successText('充值成功');
    }


    /**
     * 设备倍率调整
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 22:39
     */
    public function modifyBeilv(int $id)
    {
        $param = $this->request->param([
            'beilv' => '',
            'remark' => '',
        ]);
        validate(EnergyMeterValidate::class)->scene('modifyBeilv')->check($param);
        $meterInfo = $this->repository->get($id);
        if (!$meterInfo) {
            return $this->error('数据不存在');
        }
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }
        if ($param['beilv'] == $meterInfo['beilv']) {
            return $this->error('当前倍率一致无需更改');
        }
        $this->repository->modifyBeilv($meterInfo, $param, $this->request->userId());
        return $this->successText('修改成功');
    }

    /**
     *  设备所有权转让
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-05-18 22:53
     */
    public function makeOver(int $id)
    {
        $param = $this->request->param([
            'mobile' => '',
            'remark' => '',
        ]);
        validate(EnergyMeterValidate::class)->scene('makeOver')->check($param);
        $meterInfo = $this->repository->get($id);
        if (!$meterInfo) {
            return $this->error('数据不存在');
        }
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }
        $this->repository->makeOverInfo($meterInfo, $param, $this->request->userId());
        return $this->successText('转让成功');
    }


    /**
     * 获取设备分享二维码
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-06-07 17:05
     */
    public function getShareMeterUrl(int $id)
    {
        if (!$this->repository->exists($id)) {
            return $this->error('数据不存在');
        }
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }

        /** @var ItemsBasicRepository $repository */
        $repository = app()->make(ItemsBasicRepository::class);
        $itemsInfo = $repository->getConfig($this->request->propertyId);
        $domain = rtrim($itemsInfo['website'], '/');

        $info = $this->repository->getSearch([])
            ->where('id', $id)
            ->field('energy_no')
            ->find();
        $res['url'] = $domain . '/qrcode/energy_no?energy_no=' . $info['energy_no'];
        return app('api_return')->success($res);
    }


    /**
     * 收费方式更新
     * @param int $id
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-06-07 17:11
     */
    public function switchChargePrice(int $id)
    {
        $param = $this->request->param([
            'plan_id' => '',
            'unit_price' => ''
        ]);
        validate(EnergyMeterValidate::class)->scene('switchPlanPrice')->check($param);
        if (!$this->repository->exists($id)) {
            return $this->error('数据不存在');
        }
        if (!$this->repository->existsByUserId($id, $this->request->userId())) {
            return $this->error('权限不足');
        }

        if ($param['plan_id'] > 0) {
            $param['unit_price'] = '0.00';
        } else if ($param['unit_price'] > 0) {
            $param['plan_id'] = 0;
        }
        $this->repository->switchPlanPrice($id, $param, $this->request->userId());
        return $this->successText('更新成功');
    }

}